#!/bin/bash

if [ ! -e ./config.ini ]; then
    echo "config.ini is not exists...please check..."
    exit 1
fi

if [ -e ./env_check.log ]; then
    mv ./env_check.log ./env_check.log.bak
fi

HOSTS_IP=$(cat config.ini | sed -n '/\[hosts\]/,/\[.*\]/p' | grep -v '\[.*\]' | grep -v \^\# | grep -v \^[[:space:]]\*\$ | awk '{print $1}')
ROOT_PASS=$(cat config.ini | sed -n '/\[root_password\]/,/\[.*\]/p' | grep -v '\[.*\]' | grep -v \^\# | grep -v \^[[:space:]]\*\$)
OS_VERSION=$(cat config.ini | sed -n '/\[os_version\]/,/\[.*\]/p' | grep -v '\[.*\]' | grep -v \^\# | grep -v \^[[:space:]]\*\$)
CPU_CORES=$(cat config.ini | sed -n '/\[cpu_cores\]/,/\[.*\]/p' | grep -v '\[.*\]' | grep -v \^\# | grep -v \^[[:space:]]\*\$)
TOTAL_MEMORY=$(cat config.ini | sed -n '/\[memory_kb\]/,/\[.*\]/p' | grep -v '\[.*\]' | grep -v \^\# | grep -v \^[[:space:]]\*\$)
NUMS_OF_DISK=$(cat config.ini | sed -n '/\[data_disk_number\]/,/\[.*\]/p' | grep -v '\[.*\]' | grep -v \^\# | grep -v \^[[:space:]]\*\$)
PARTITION_SIZE=$(cat config.ini | sed -n '/\[root_partition_size\]/,/\[.*\]/p' | grep -v '\[.*\]' | grep -v \^\# | grep -v \^[[:space:]]\*\$)
TIME_VALUE=$(cat config.ini | sed -n '/\[time_sync_diff\]/,/\[.*\]/p' | grep -v '\[.*\]' | grep -v \^\# | grep -v \^[[:space:]]\*\$)

if [[ "$HOSTS_IP" == "" ]]; then
    echo "No Host IP address is configured in config.ini,Please check ./config.ini"
    exit 1
else
    echo "The cluster includes the following hosts:"
    for host in $HOSTS_IP; do
        echo $host
    done
    read -p "Please confirm,input yes/no:" choice
    if [[ "$choice" == "yes" || $choice == "YES" || "$choice" == "Y" || "$choice" == "y" ]]; then
        echo ""
    else
        exit 1
    fi
fi

function format_print() {
    if [ $# -lt 1 ]; then
        echo "Usage:format print 'args1 args2...'"
    fi
    for str in $@; do
        echo $str
    done
}

function check_host_online() {
    echo "++++++1、检查集群连通性++++++"
    for host in $HOSTS_IP; do
        ping -w 3 $host &>/dev/null
        if [ $? -eq 0 ]; then
            echo "检查主机 $host 连通性通过"
        else
            echo "检查主机 $host 连通性失败,无法连通"
            ping_failed_hosts="$ping_failed_hosts $host"
        fi
    done
    if [[ "$ping_failed_hosts" == "" ]]; then
        echo "1、使用ping对集群主机连通性检查,全部通过" | tee -a ./env_check.log
    else
        echo "1、使用ping对集群主机连通性检查,未全部通过。以下主机无法连通:" | tee -a ./env_check.log
        format_print $ping_failed_hosts | tee -a ./env_check.log
        exit 1
    fi
}
##
## 检测是否通过ssh连接上主机
## 参数1:主机的ip
## 参数2:主机的密码
function verify_password() {
    if [ $# -lt 2 ]; then
        echo "Usage:verify_password IP root_password"
        exit 1
    fi
    sshpass -p$2 ssh -o StrictHostKeyChecking=no root@$1 "uptime" &>/dev/null
    if [ $? -ne 0 ]; then
        echo "尝试通过SSH登录主机 $1 失败,请检测后重试脚本"
        return 255
    else
        return 0
    fi
}

function check_os_version() {
    echo "++++++2、检查集群主机操作系统版本与目标版本($OS_VERSION)一致性++++++"
    for host in $HOSTS_IP; do
        verify_password $host $ROOT_PASS
        if [ $? -eq 0 ]; then
            sshpass -p$ROOT_PASS ssh -o StrictHostKeyChecking=no root@$host "grep $OS_VERSION /etc/redhat-release" &>/dev/null
            if [ $? -ne 0 ]; then
                echo "检查主机 $host 操作系统版本与目标($OS_VERSION)不一致,未通过"
                os_failed_hosts="$os_failed_hosts $host"
            else
                echo "检查主机 $host 操作系统版本与目标($OS_VERSION)一致,检查通过"
            fi
        else
            os_failed_hosts="$os_failed_hosts $host"
        fi
    done
    if [[ $os_failed_hosts == "" ]]; then
        echo "2、检查集群主机OS版本与目标版本($OS_VERSION)一致性,全部通过" | tee -a ./env_check.log
    else
        echo "2、检查集群主机OS版本与目标版本($OS_VERSION)一致性,不通过。未通过的主机:" | tee -a ./env_check.log
        format_print $os_failed_hosts | tee -a ./env_check.log
    fi
}

function check_cpu_cores() {
    echo "++++++3、检查集群主机CPU规格(逻辑核数不低于$CPU_CORES)++++++"
    for host in $HOSTS_IP; do
        verify_password $host $ROOT_PASS
        if [ $? -eq 0 ]; then
            DST_CPU_CORES=$(sshpass -p$ROOT_PASS ssh -o StrictHostKeyChecking=no root@$host "cat /proc/cpuinfo | grep ^processor | sort | uniq | wc -l")
            if [ $DST_CPU_CORES -lt $CPU_CORES ]; then
                echo "检查主机 $host CPU逻辑核心数量不通过"
                cpu_failed_hosts="$cpu_failed_hosts $host"
            else
                echo "检查主机 $host CPU逻辑核心数量通过"
            fi
        else
            cpu_failed_hosts="$cpu_failed_hosts $host"
        fi
    done
    if [[ $cpu_failed_hosts == "" ]]; then
        echo "3、检查集群主机CPU核心数量是否大于等于$CPU_CORES,全部通过" | tee -a ./env_check.log
    else
        echo "3、检查集群主机CPU核心数量是否大于等于$CPU_CORES,不通过。未通过的主机:" | tee -a ./env_check.log
        format_print $cpu_failed_hosts | tee -a ./env_check.log
    fi
}

function check_memory() {
    echo "++++++4、检查集群主机内存规格(大于等于$TOTAL_MEMORY kb)++++++"
    for host in $HOSTS_IP; do
        verify_password $host $ROOT_PASS
        if [ $? -eq 0 ]; then
            DST_TOTAL_MEMORY=$(sshpass -p$ROOT_PASS ssh -o StrictHostKeyChecking=no root@$host "cat /proc/meminfo | grep MemTotal | awk '{print \$2}'")
            if [ $DST_TOTAL_MEMORY -lt $TOTAL_MEMORY ]; then
                echo "检查主机 $host 内存大小不通过"
                mem_failed_hosts="$mem_failed_hosts $host"
            else
                echo "检查主机 $host 内存大小不通过"
            fi
        else
            mem_failed_hosts="$mem_failed_hosts $host"
        fi
    done
    if [[ $mem_failed_hosts == "" ]]; then
        echo "4、检查集群主机内存大小是否满足规格(大于等于$TOTAL_MEMORY kb),全部通过" | tee -a ./env_check.log
    else
        echo "4、检查集群主机内存大小是否满足规格(大于等于$TOTAL_MEMORY kb),不通过。未通过的主机:" | tee -a ./env_check.log
        format_print $mem_failed_hosts | tee -a ./env_check.log
    fi
}

function check_disk_number() {
    echo "++++++5、检查集群主机数据磁盘个数(不低于$NUMS_OF_DISK)++++++"
    for host in $HOSTS_IP; do
        verify_password $host $ROOT_PASS
        ALL_DISK_NUMBER=$(sshpass -p$ROOT_PASS ssh -o StrictHostKeyChecking=no root@$host "lsscsi | awk '\$2~/disk/{print \$8}'")
        for d in $ALL_DISK_NUMBER; do
            df -h | grep "%d" &>/dev/null
            if [ $? -eq 0 ]; then
                DATA_DISK_SYMBOLS=$(echo $ALL_DISK_NUMBER | sed "s#$d##g")
            fi
        done
        DATA_DISK_NUMBER=$(echo $DATA_DISK_SYMBOLS | awk '{print NF}')
        if [ $DATA_DISK_NUMBER -ge $NUMS_OF_DISK ]; then
            echo "检查主机 $host 数据盘个数通过"
        else
            echo "检查主机 $host 数据盘个数不通过,数据盘个数小于$NUMS_OF_DISK"
            disk_failed_hosts="$disk_failed_hosts $host"
        fi
    done
    if [[ $disk_failed_hosts == "" ]]; then
        echo "5、检查集群主机数据磁盘个数,全部通过" | tee -a ./env_check.log
    else
        echo "5、检查集群主机数据磁盘个数,未全部通过。以下主机磁盘个数小于$NUMS_OF_DISK:" | tee -a ./env_check.log
        format_print $disk_failed_hosts | tee -a ./env_check.log
    fi
}

function check_root_partition_size() {
    echo "++++++6、检查集群主机根分区大小(不低于$PARTITION_SIZE G)++++++"
    for host in $HOSTS_IP; do
        verify_password $host $ROOT_PASS
        if [ $? -eq 0 ]; then
            ROOT_PARTITION_SIZE=$(sshpass -p$ROOT_PASS ssh -o StrictHostKeyChecking=no root@$host "df -h | awk '\$6==\"/\"{print \$2}' | sed 's/[^0-9]//g'")
            if [ $ROOT_PARTITION_SIZE -lt $PARTITION_SIZE ]; then
                echo "检查主机 $host 根分区/大小,小于$PARTITION_SIZE G,检查不通过"
                part_failed_hosts="$part_failed_hosts $host"
            else
                echo "检查主机 $host 根分区/大小,小于$PARTITION_SIZE G,检查通过"
            fi
        else
            part_failed_hosts="$part_failed_hosts $host"
        fi
    done
    if [[ $part_failed_hosts == "" ]]; then
        echo "6、检查集群主机根分区/大小,大于等于$PARTITION_SIZE G,全部通过" | tee -a ./env_check.log
    else
        echo "6、检查集群主机根分区/大小,大于等于$PARTITION_SIZE G,未全部通过。失败的主机:" | tee -a ./env_check.log
        format_print $part_failed_hosts | tee -a ./env_check.log
    fi
}

function check_timesync() {
    echo "++++++7、检查集群主机时间是否同步(误差不超过$TIME_VALUE秒)++++++"
    for host in $HOSTS_IP; do
        LOCAL_TIME=$(date "+%Y%m%d%H%M%S")
        verify_password $host $ROOT_PASS
        if [ $? -eq 0 ]; then
            DST_HOST_TIME=$(sshpass -p$ROOT_PASS ssh -o StrictHostKeyChecking=no root@$host "date '+%Y%m%d%H%M%S'")
            TIME_DIFF=$(expr $LOCAL_TIME - $DST_HOST_TIME | sed 's/[^0-9]//g')
            if [ $TIME_DIFF -lt $TIME_VALUE ]; then
                echo "检查主机 $host 时间同步通过"
            else
                echo "检查主机 $host 时间同步不通过。时间误差在$TIME_DIFF秒"
                time_failed_hosts="$time_failed_hosts $host"
            fi
        else
            time_failed_hosts="$time_failed_hosts $host"
        fi
    done
    if [[ $time_failed_hosts == "" ]]; then
        echo "7、检查集群主机时间是否同步,全部通过" | tee -a ./env_check.log
    else
        echo "7、检查集群主机时间是否同步,未全部通过。时间不同步的主机包括:" | tee -a ./env_check.log
        format_print $time_failed_hosts | tee -a ./env_check.log
    fi
}

check_host_online
check_os_version
check_cpu_cores
check_memory
check_disk_number
check_root_partition_size
check_timesync
